import config from '@/config/index.js'

// 请求队列（用于防止重复请求）
const pendingRequests = new Map()

/**
 * 生成请求标识
 * @param {Object} config 请求配置
 * @returns {String} 请求标识
 */
function generateReqKey(config) {
  const { method, url, data } = config
  // 对于GET请求，使用params；对于POST等请求，使用data
  const requestData = method.toUpperCase() === 'GET' ? config.params : data
  return [method, url, JSON.stringify(requestData)].join('&')
}

/**
 * 添加请求到队列
 * @param {Object} config 请求配置
 */
function addPendingRequest(config) {
  const requestKey = generateReqKey(config)
  // 使用uni.request的abort方法取消请求
  if (pendingRequests.has(requestKey)) {
    const previousTask = pendingRequests.get(requestKey)
    previousTask.abort && previousTask.abort()
  }
  
  // 存储请求标识和配置
  pendingRequests.set(requestKey, {
    timestamp: Date.now(),
    config: config
  })
}

/**
 * 从队列中移除请求
 * @param {Object} config 请求配置
 */
function removePendingRequest(config) {
  const requestKey = generateReqKey(config)
  if (pendingRequests.has(requestKey)) {
    pendingRequests.delete(requestKey)
  }
}

/**
 * 清除所有pending状态的请求
 */
export function clearPendingRequests() {
  for (const [requestKey, requestInfo] of pendingRequests) {
    const task = requestInfo.task
    if (task && task.abort) {
      task.abort()
    }
  }
  pendingRequests.clear()
}

/**
 * 请求拦截器
 * @param {Object} options 请求选项
 * @returns {Object} 处理后的请求选项
 */
function requestInterceptor(options) {
  // 添加token到请求头
  const token = uni.getStorageSync('token')
  if (token) {
    options.header = {
      ...options.header,
      'Authorization': `Bearer ${token}`
    }
  }
  
  // 处理请求URL
  if (options.url.startsWith('http')) {
    options.url = options.url
  } else {
    options.url = config.baseURL + options.url
  }
  
  // 设置超时时间
  options.timeout = options.timeout || config.timeout
  
  return options
}

/**
 * 响应拦截器
 * @param {Object} response 响应对象
 * @param {Object} requestConfig 请求配置
 * @returns {Object} 处理后的响应数据
 */
function responseInterceptor(response, requestConfig) {
  const { statusCode, data } = response
  
  // 从请求队列中移除
  removePendingRequest(requestConfig)
  
  // HTTP状态码判断
  if (statusCode === 200) {
    // 业务状态码判断（根据实际API结构调整）
    if (data.code === 0 || data.code === 200 || data.success) {
      return data.data !== undefined ? data.data : data
    } else {
      // 业务错误
      const error = new Error(data.message || data.msg || '业务错误')
      error.code = data.code
      error.data = data
      throw error
    }
  } else {
    // HTTP错误
    const error = new Error(`HTTP错误: ${statusCode}`)
    error.statusCode = statusCode
    throw error
  }
}

/**
 * 错误处理
 * @param {Error} error 错误对象
 * @param {Object} requestConfig 请求配置
 * @returns {Promise} 错误Promise
 */
function errorHandler(error, requestConfig) {
  // 从请求队列中移除
  if (requestConfig) {
    removePendingRequest(requestConfig)
  }
  
  // 错误信息处理
  let errorMessage = '网络请求失败'
  
  if (error.errMsg) {
    if (error.errMsg.includes('timeout')) {
      errorMessage = '请求超时，请检查网络连接'
    } else if (error.errMsg.includes('request:fail')) {
      errorMessage = '网络连接失败，请检查网络设置'
    }
  } else if (error.msg) {
    errorMessage = error.msg
  }
  
  // 显示错误提示（非生产环境可以显示详细错误）
  if (process.env.NODE_ENV === 'development') {
    console.error('请求错误:', error)
  }
  
  uni.showToast({
    title: errorMessage,
    icon: 'none',
    duration: 3000
  })
  
  // token过期处理
  if (error.code === 401) {
    // 清除token并跳转到登录页
    uni.removeStorageSync('token')
    uni.removeStorageSync('userInfo')
    uni.reLaunch({
      url: '/pages/login/login'
    })
  }
  
  return Promise.reject(error)
}

/**
 * 封装的请求方法
 * @param {Object} options 请求配置
 * @returns {Promise} 请求Promise
 */
function request(options) {
  // 合并配置
  const requestOptions = {
    ...config,
    ...options,
    header: {
      ...config.header,
      ...options.header
    }
  }
  
  // 请求拦截
  const processedOptions = requestInterceptor(requestOptions)
  
  // 添加到请求队列
  addPendingRequest(processedOptions)
  
  return new Promise((resolve, reject) => {
    const requestTask = uni.request({
      ...processedOptions,
      success: (response) => {
        try {
          const data = responseInterceptor(response, processedOptions)
          resolve(data)
        } catch (error) {
          reject(errorHandler(error, processedOptions))
        }
      },
      fail: (error) => {
        reject(errorHandler(error, processedOptions))
      }
    })
    
    // 存储请求任务用于取消
    const requestKey = generateReqKey(processedOptions)
    if (pendingRequests.has(requestKey)) {
      const requestInfo = pendingRequests.get(requestKey)
      requestInfo.task = requestTask
      pendingRequests.set(requestKey, requestInfo)
    }
  })
}

/**
 * GET请求
 * @param {String} url 请求地址
 * @param {Object} params 请求参数
 * @param {Object} options 其他选项
 * @returns {Promise}
 */
export function get(url, params = {}, options = {}) {
  return request({
    url,
    method: 'GET',
    data: params,
    ...options
  })
}

/**
 * POST请求
 * @param {String} url 请求地址
 * @param {Object} data 请求数据
 * @param {Object} options 其他选项
 * @returns {Promise}
 */
export function post(url, data = {}, options = {}) {
  return request({
    url,
    method: 'POST',
    data,
    ...options
  })
}

/**
 * PUT请求
 * @param {String} url 请求地址
 * @param {Object} data 请求数据
 * @param {Object} options 其他选项
 * @returns {Promise}
 */
export function put(url, data = {}, options = {}) {
  return request({
    url,
    method: 'PUT',
    data,
    ...options
  })
}

/**
 * DELETE请求
 * @param {String} url 请求地址
 * @param {Object} data 请求数据
 * @param {Object} options 其他选项
 * @returns {Promise}
 */
export function del(url, data = {}, options = {}) {
  return request({
    url,
    method: 'DELETE',
    data,
    ...options
  })
}

/**
 * 上传文件
 * @param {String} url 上传地址
 * @param {Object} formData 表单数据
 * @param {String} filePath 文件路径
 * @param {String} name 文件字段名
 * @param {Object} options 其他选项
 * @returns {Promise}
 */
export function uploadFile(url, formData = {}, filePath, name = 'file', options = {}) {
  return new Promise((resolve, reject) => {
    const uploadTask = uni.uploadFile({
      url: config.baseURL + url,
      filePath,
      name,
      formData,
      header: {
        'Authorization': `Bearer ${uni.getStorageSync('token')}`
      },
      success: (response) => {
        if (response.statusCode === 200) {
          try {
            const data = JSON.parse(response.data)
            if (data.code === 0 || data.code === 200 || data.success) {
				console.log(data)
              resolve(data.data !== undefined ? data.data : data)
            } else {
              reject(new Error(data.message || data.msg || '上传失败'))
            }
          } catch (e) {
            reject(new Error('响应数据解析失败'))
          }
        } else {
          reject(new Error(`上传失败: ${response.statusCode}`))
        }
      },
      fail: (error) => {
        reject(errorHandler(error))
      },
      ...options
    })
    
    // 可选：返回上传任务用于监听进度
    if (options.onProgressUpdate && typeof options.onProgressUpdate === 'function') {
      uploadTask.onProgressUpdate(options.onProgressUpdate)
    }
  })
}

/**
 * 下载文件
 * @param {String} url 下载地址
 * @param {Object} options 其他选项
 * @returns {Promise}
 */
export function downloadFile(url, options = {}) {
  return new Promise((resolve, reject) => {
    const downloadTask = uni.downloadFile({
      url: config.baseURL + url,
      header: {
        'Authorization': `Bearer ${uni.getStorageSync('token')}`
      },
      success: (response) => {
        if (response.statusCode === 200) {
          resolve(response.tempFilePath)
        } else {
          reject(new Error(`下载失败: ${response.statusCode}`))
        }
      },
      fail: (error) => {
        reject(errorHandler(error))
      },
      ...options
    })
    
    // 可选：返回下载任务用于监听进度
    if (options.onProgressUpdate && typeof options.onProgressUpdate === 'function') {
      downloadTask.onProgressUpdate(options.onProgressUpdate)
    }
  })
}

/**
 * 取消请求
 * @param {String} url 请求URL
 * @param {Object} params 请求参数
 */
export function cancelRequest(url, params = {}) {
  const requestKey = generateReqKey({
    method: 'GET', // 默认为GET，实际应根据具体情况
    url,
    params
  })
  
  if (pendingRequests.has(requestKey)) {
    const requestInfo = pendingRequests.get(requestKey)
    if (requestInfo.task && requestInfo.task.abort) {
      requestInfo.task.abort()
    }
    pendingRequests.delete(requestKey)
  }
}

export default {
  get,
  post,
  put,
  del,
  uploadFile,
  downloadFile,
  cancelRequest,
  clearPendingRequests
}